package practica3;

import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.bayes.BayesNet;
import weka.classifiers.bayes.net.search.global.K2;
import weka.core.Instances;

/**Clase que entrena el clasificador BayesNet mediante una evaluacion no-honesta*/
public class UpperBoundsAlgorithm {
		
	private Evaluation bestEvaluator = null;
	
	public UpperBoundsAlgorithm(){}
		
	/**
	* Metodo que entrena el BayesNet y realiza una evaluacion no-honesta.
	* @param data
	* @return
	 */
	public void classify(Instances data) throws Exception{
		double fmeasure = -1, fmeasureMax = -1;	
		int bestP = -1;
		K2 sa = new K2(); //Algoritmo de búsqueda
		BayesNet estimador = new BayesNet();
		Evaluation evaluator = null; 
		estimador.setSearchAlgorithm(sa);	

		for(int p = 1; p<data.numAttributes(); p++){
				
			sa.setMaxNrOfParents(p); //Número de padres
			for(int n = 0; n<=1; n++){			 	
				if(n==0)
					sa.setInitAsNaiveBayes(false);
				else 
					sa.setInitAsNaiveBayes(true);//Tiene padre
					
				evaluator = new Evaluation(data); 
				estimador.setSearchAlgorithm(sa);
				evaluator = this.simpleClassify(estimador, data, data);

				fmeasure = evaluator.weightedFMeasure();
				
				if(fmeasure>fmeasureMax){
					bestP = p;
					fmeasureMax = fmeasure;
					this.bestEvaluator = evaluator;
				}
			}
		}	
		this.print(bestP);				
	}
		
	/**
	* Metodo que imprime los resultados del barrido de parametros realizado por el clasificador.
	* @param bestP  
	* @param desc mejor f-Measure obtenida por el clasificador.
	* @param  valor de la red inicial.
	*/
	private void print(int bestP) throws Exception{		
		System.out.println("\nCALIDAD MAXIMA (NO-HONESTO)");
		System.out.println("-----------------------------");
		System.out.println("Mejor valor de p (numero de atributos minimo) = " + bestP +"\n");
		System.out.println(this.bestEvaluator.toClassDetailsString());
		System.out.println(this.bestEvaluator.toSummaryString());
		System.out.println(this.bestEvaluator.toMatrixString());	
	}
		
	/**
	* Metodo que saca el evaluador no-honesto
	* @param model
	* @param trainingSet
	* @param testingSet
	* @return
	*/
	public Evaluation simpleClassify(Classifier model, Instances trainingSet, Instances testingSet) throws Exception {
		Evaluation validation = new Evaluation(trainingSet);
		model.buildClassifier(trainingSet);
		validation.evaluateModel(model, testingSet);
		return validation;
	}
	
	public Evaluation getEvaluador(){
		return this.bestEvaluator;
	}
}
